Data Types
This section describes some of the general-purpose data types that the Memory Manager defines. These data types are used throughout the Macintosh Toolbox and Operating System.Pointers and Handles
As you've seen, the Memory Manager uses pointers and handles to reference nonrelocatable and relocatable blocks, respectively. The data typesPtr
andHandle
define pointers and handles as follows:
TYPE SignedByte = -128..127; {any byte in memory} Byte = 0..255; {an unsigned byte} Ptr = ^SignedByte; {address of a signed byte} Handle = ^Ptr; {address of a master pointer}TheSignedByte
data type stands for an arbitrary byte in memory, just to givePtr
andHandle
something to point to. TheByte
data type is an alternative definition that treats byte-length data as an unsigned rather than a signed quantity.The Pascal language defines the special symbol
NIL
, which can be the value of any pointer type. You can assignNIL
to any pointer (and hence to any handle) to indicate that the pointer has a defined value but does not point anywhere useful. Some system software routines returnNIL
as the value of a pointer or handle if the routine fails to perform the requested action. For example, theNewHandle
routine returnsNIL
if the requested amount of memory is not available in the application heap.For C, the type declarations look like this:
typedef char SignedByte; /*any byte in memory*/ typedef unsigned char Byte; /*an unsigned byte*/ typedef char *Ptr; /*address of a signed byte*/ typedef Ptr *Handle; /*address of a master pointer*/Unlike Pascal, the C language does not contain a reserved symbol for a nil pointer. Most development systems, however, include definitions of bothnil
andNULL
:
#define NULL 0 #define nil 0Because of C's loose type conventions, you can assign the valuesnil
andNULL
to data types other than pointers and handles. In Pascal, the compiler generates an error if you try to assign the valueNIL
to an object whose data type is not defined as a pointer to some data type.Strings
The Macintosh system software uses strings in arrays of up to 255 characters, with the first byte of the array storing the length of the string. Some Toolbox routines allow you to pass such a string directly; others require that you pass a pointer or a handle to a string. The Memory Manager provides the following type definitions that define character strings in terms of the PascalString
data type:
TYPE Str15 = String[15]; Str27 = String[27]; Str31 = String[31]; Str63 = String[63]; Str255 = String[255]; StringPtr = ^Str255; StringHandle = ^StringPtr;The C language treats strings differently than Pascal does. In C, strings are of variable length, with the end of the string marked by a special delimiter, usually the null character (ASCII 0). If you are using C, you must make certain to pass Pascal-style strings to Toolbox routines or to use special versions of the Toolbox routines that accept C strings. Check the documentation for your development environment for complete details.Procedure Pointers
For treating procedures and functions as data objects, the Memory Manager defines theProcPtr
data type:
TYPE ProcPtr = Ptr; {pointer to a procedure}For example, after the declarations
VAR myProcPtr: ProcPtr; PROCEDURE MyProc; BEGIN ... END;you can makemyProcPtr
reference theMyProc
procedure by using Pascal's@
operator, as follows:
myProcPtr := @MyProc;With the@
operator, you can assign procedures and functions to variables of typeProcPtr
, embed them in data structures, and pass them as arguments to other routines. Notice, however, that the data typeProcPtr
technically points to an arbitrary byte, not an actual routine. As a result, there's no way in Pascal to access the underlying routine via this pointer in order to call it. Only routines written in assembly language can actually call routines designated by pointers of typeProcPtr
.
- Note
- You can't use the
@
operator to reference procedures or functions whose declarations are nested within other routines.![]()
Type Coercion
Because of Pascal's strong typing rules, you can't directly assign a pointer value to a variable of some other pointer type, or pass a pointer variable to a routine requesting some other pointer type. Instead, you have to coerce the pointer from one type to another.For example, you can call the
HLock
procedure to lock a relocatable block of memory. TheHLock
procedure requires a parameter of typeHandle
. If the block you want to lock isn't referenced by a variable of typeHandle
, you must coerce the variable to the required type. Here's an example:
HLock(Handle(myData));Similarly, theGetDialogItem
procedure returns in aVAR
parameter a handle to an item in a dialog box. If you were to use the procedure to obtain the handle to a button in the variableitemHand
of typeHandle
, you might need to access the button as a control. For example, you could access the button's enclosing rectangle with the code:
ControlHandle(itemHand)^^.contrlRect;You can use this same syntax to equate any two variables of the same length. For example:
VAR myChar: Char; myByte: Byte; myByte := Byte(myChar);You can also use the functionsORD
,ORD4
, andPOINTER
to coerce variables of different length from one type to another. For example:
VAR myInteger: Integer; myLongInt: LongInt; myPointer: Ptr; myInteger := ORD(myLongInt); {two low-order bytes only} myInteger := ORD(myPointer); {two low-order bytes only} myLongInt := ORD(myInteger); {packed into high-order bytes} myLongInt := ORD4(myInteger); {packed into low-order bytes} myLongInt := ORD(myPointer); myPointer := POINTER(myInteger); myPointer := POINTER(myLongInt);
- Note
- Assembly-language and C language programmers don't need to bother with type coercion.
![]()